# 迭代器iterable
# 可迭代数据类型: str,list,tuple,dict,set
# 1.2 可迭代对象的条件
# 1.对象实现了__iter__()方法
# 2.__iter__()方法返回了迭代器对象
# 1.3 for循环工作原理
# 1.先通过 iter ()获取可迭代对象的迭代器
# 2.对获取到的迭代器不断调用_next ()方法来获取下一个值并将其赋值给临时变量i
# 1.4isinstance():判断一个对象是否是可迭代对象或者是一个已知的数据类型
# from collections.abc import Iterable
# isinstance(o,t) o:对象, t:类型
print(isinstance('123',(str,dict)))

# 2. 迭代器
# 一个可以记住遍历位置的对象;在上次停留的位置继续去做一些事情
# iter(): 获取可迭代对象的迭代器
# next(): 一个个去取元素,不能取超过索引
# 创建迭代器对象
li = [1,2,3,4,5]
li2 = iter(li)
# print(next(li2))
# print(next(li2))
# print(next(li2))
# print(next(li2))
# print(next(li2))
# 方法二
li2 = li.__iter__()
print(next(li2))
print(next(li2))
print(next(li2))
print(next(li2))
print(next(li2))

#步骤:
#1.iter()调用对象的 iter (),并把 iter ()方法的返回结果作为自己的返回值
#2.next()调用对象的next()，一个个取元素
#3.所有元素都取完了,next ()将引发StopIteration异常


# 2.2可迭代对象iterable和迭代器iterator
# 凡是可以作用于for循环的都属于可迭代对象
# 凡是可以作用于next()的都是迭代器
from collections.abc import Iterable,Iterator
name = 'ljjee'
print(isinstance(name,Iterable))
print(isinstance(name,Iterator))
# 将name转为迭代器对象
name2 = iter(name)
print(isinstance(name,Iterable))
print(isinstance(name2,Iterator))
# 可迭代对象不一定是迭代器对象
# 迭代器对象,一定是可迭代对象
# 总结:
# 可迭代对象可以通过iter()转换成迭代器对象
# 如果一个对象拥有_iter_()，是可迭代对象，如果一个对象拥有_next_()和_iter_()方法，是迭代器对象
# dir():查看对象中的属性和方法
# 2.3 迭代器协议
# 对象必须提供一个后续方法，执行该方法要么就返回迭代中的下一项，要么就引发Stoplteration异常，来终止迭代
# 2.4 自定义迭代器类
class Test(object):
    def __init__(self):
        self.num = 0
    def funa(self):
        self.num += 1
        return self.num
te = Test()

# print(te.funa())
# print(te.funa())

class MyIterator(object):
    def __init__(self):
        self.num = 1
    def __iter__(self):
        return self   # 返回的是当前迭代器类的实例对象
    def __next__(self):
        if self.num == 10:
            raise StopIteration("终止迭代,数据已经被取完")
        self.num += 1
        return self.num

mi = MyIterator()
# print(next(mi))
for i in mi:
    print(i)

